/*
 * AnalysePath.java
 *
 * Created on January 30, 2007, 11:18 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package net.sf.iSnake.aimodule;

import java.util.Vector;
import net.sf.iSnake.core.FoodGenerator;
import net.sf.iSnake.core.GameAreaCoordinate;
import net.sf.iSnake.core.RandomNumberGenerator;
import net.sf.iSnake.core.Snake;

/**
 *
 * @author Administrator
 */
public class AnalysePath extends Thread{
    final int UP=0,DOWN=1,RIGHT=2,LEFT=3;
    final int UP_RIGHT=4,UP_LEFT=5,DOWN_RIGHT=6,DOWN_LEFT=7,HORIZONTAL=8,VERTICAL=9;

    int xl_head,yl_head,xh_head,yh_head,count_head=0;
    int count_endPoint[]=new int[3];
    boolean reachable[][]=new boolean[4][5];
    
    int dir;
    boolean fullPathBlocked=false;
    boolean fullPathFree=false;
    boolean endPointPresent[]={false,false,false};
    byte node=-1;
    
    int hor[]=new int[2];
    int ver[]=new int[2];
    int foodx,foody,headx,heady;
    Short source_dest_dir1[]=new Short[2];
    Short source_dest_dir2[]=new Short[2];
    Short temp[]=new Short[2];
    
    AnalyseWall w;
    
    Snake s;
    short source_destMove[][];
    int virtualendPoint[][]=new int[3][2];
    Vector finalPath;
    /** Creates a new instance of AnalysePath */
    public AnalysePath(AnalyseWall w, GameAreaCoordinate f, Snake s) {
        this.w=w;
        this.s=s;
        headx=(((GameAreaCoordinate)(s.getHead())).getX());
        heady=(((GameAreaCoordinate)(s.getHead())).getY());
//        f.generateNewFoodCoordinate();
//        foodx=(((GameAreaCoordinate)(f.getCurrentFoodCoordinate())).getX());
//        foody=(((GameAreaCoordinate)(f.getCurrentFoodCoordinate())).getY());
        foodx=f.getX();
        foody=f.getY();
        finalPath=new Vector();
        this.start();
    }
    public void run(){
        initParameters();
        setVirtual();
        head_Food_Dir_Boundary();
        count_endPoint();
        if(!reachable[3][4]){
            reachable_head();
            intermediateNode();
            if(node>=0){
                pathlength(0,headx,heady,virtualendPoint[node][0],virtualendPoint[node][1]);
                pathlength(1,virtualendPoint[node][0],virtualendPoint[node][1],foodx,foody);
                storePath(0);
                storePath(1);
            }
        }
        if(node==-1){
            pathlength(0,headx,heady,foodx,foody);
            storePath(0);
        }
       System.out.println("ISNAKE: Path analysed...");
    }
    public void initParameters(){
        for(int i=0;i<3;i++){
            virtualendPoint[i][0]=w.endPoint[i][0];
            virtualendPoint[i][1]=w.endPoint[i][1];
            for(int j=0;j<=4;j++)
                reachable[i][j]=true;
        }
    }
    public void setVirtual(){
        switch(w.dir){
            case UP_RIGHT:
                virtualendPoint[0][0]--;
                virtualendPoint[2][1]--;
            case UP_LEFT:
                virtualendPoint[0][0]++;
                virtualendPoint[2][1]--;
                break;
            case DOWN_RIGHT:
                virtualendPoint[0][0]--;
                virtualendPoint[2][1]++;
                break;
            case DOWN_LEFT:
                virtualendPoint[0][0]++;
                virtualendPoint[2][1]++;
                break;
        }
    }
    public void head_Food_Dir_Boundary(){
        if(headx<foodx){
            xl_head=headx;
            xh_head=foodx;
            if(heady>foody){
                dir=UP_RIGHT;
                yl_head=foody;
                yh_head=heady;
            }
            if(heady<foody){
                dir=DOWN_RIGHT;
                yl_head=heady;
                yh_head=foody;
            }
        }
        if(headx>foodx){
            xl_head=foodx;
            xh_head=headx;
            if(heady>foody){
                dir=UP_LEFT;
                yl_head=foody;
                yh_head=heady;
            }
            if(heady<foody){
                dir=DOWN_LEFT;
                yl_head=heady;
                yh_head=foody;
            }
        }
    }
    public void count_endPoint(){
        for(int i=0;i<3;i++){
            if(w.endPoint[i][0]>=xl_head&&w.endPoint[i][0]<=xh_head&&w.endPoint[i][1]>=yl_head&&w.endPoint[i][1]<=yh_head){
                endPointPresent[i]=true;
                count_head++;
            }
        }
        if(endPointPresent[1]){
            if(11-w.endPoint[1][2]!=dir){   //try even if endPointPresent[1]=false.
                reachable[1][0]=false;
                reachable[1][2]=false;
            }
            if(w.endPoint[1][2]!=dir){
                reachable[0][1]=false;
                reachable[2][1]=false;
            }
            else{
                reachable[3][1]=false;
            }
        }
        if(count_head==0){
            for(int index=0;index<w.wall.size();index++){
                if(checkfull()){
                    fullPathBlocked=true;
                    break;
                }
                else
                    fullPathBlocked=false;
            }
            if(!fullPathBlocked)
                fullPathFree=true;
        }
        if(count_head==1){
            if(endPointPresent[0]){
                if(w.endPoint[0][0]==xl_head||w.endPoint[0][0]==xh_head||w.endPoint[0][1]==yl_head||w.endPoint[0][1]==yh_head){
                    if(!checkfull()){
                        fullPathFree=true;
                    }
                }
            }
            if(endPointPresent[1]){
                if(w.endPoint[1][0]==xl_head||w.endPoint[1][0]==xh_head||w.endPoint[1][1]==yl_head||w.endPoint[1][1]==yh_head){
                    if(!(abscissawall(w.corner)>=xl_head&&abscissawall(w.corner)<=xh_head&&ordinatewall(w.corner)>=yl_head&&ordinatewall(w.corner)<=yh_head)){
                        fullPathFree=true;
                    }
                }
            }
            if(endPointPresent[2]){
                if(w.endPoint[2][0]==xl_head||w.endPoint[2][0]==xh_head||w.endPoint[2][1]==yl_head||w.endPoint[2][1]==yh_head){
                    if(!(abscissawall(w.len-1)>=xl_head&&abscissawall(w.len-1)<=xh_head&&ordinatewall(w.len-1)>=yl_head&&ordinatewall(w.len-1)<=yh_head)){
                        fullPathFree=true;
                    }
                }
            }
        }
        if(!fullPathFree)
            reachable[3][4]=false;
    }
    public void reachable_head(){
        if(endPointPresent[0]){
            if((w.dir==11-dir)){
                reachable[0][4]=false;
                if((dir==UP_RIGHT||dir==UP_LEFT)&&w.endPoint[2][1]>yh_head){
                    reachable[0][4]=true;
                    reachable[1][4]=false;
                }
                if((dir==DOWN_RIGHT||dir==DOWN_LEFT)&&w.endPoint[2][1]<yl_head){
                    reachable[0][4]=true;
                    reachable[1][4]=false;
                }
            }
            if(w.dir==dir){           
                reachable[3][0]=false;
                if((dir==UP_RIGHT||dir==UP_LEFT)&&w.endPoint[2][1]<yl_head){
                    reachable[3][0]=true;
                    reachable[3][1]=false;
                }
                if((dir==DOWN_RIGHT||dir==DOWN_LEFT)&&w.endPoint[2][1]>yh_head){
                    reachable[3][0]=true;
                    reachable[3][1]=false;
                }
            }
            else
                reachable[2][0]=false;
            switch(dir){
                case UP_RIGHT:
                case UP_LEFT:
                    if(w.endPoint[0][1]==heady&&w.endPoint[0][2]==DOWN){
                        reachable[0][4]=false;
                        break;
                    }
                case DOWN_RIGHT:
                case DOWN_LEFT:
                    if(w.endPoint[0][1]==heady&&w.endPoint[0][2]==UP){
                        reachable[0][4]=false;
                        break;
                    }
            }
        }
        if(endPointPresent[2]){
            if(w.dir==dir){
                reachable[2][4]=false;
                if((dir==UP_RIGHT||dir==DOWN_RIGHT)&&w.endPoint[0][0]<xl_head){
                    reachable[2][4]=true;
                    reachable[3][1]=false;
                }
                if((dir==UP_LEFT||dir==DOWN_LEFT)&&w.endPoint[0][0]>xh_head){
                    reachable[2][4]=true;
                    reachable[3][1]=false;
                }
            }
            if(11-w.dir==dir){
                reachable[3][2]=false;
                if((dir==UP_RIGHT||dir==DOWN_RIGHT)&&w.endPoint[0][0]>xh_head)
                    reachable[3][2]=true;
                if((dir==UP_LEFT||dir==DOWN_LEFT)&&w.endPoint[0][0]<xl_head)
                    reachable[3][2]=true;
            }
            else
                reachable[0][2]=false;
            switch(dir){
                case UP_RIGHT:
                case DOWN_RIGHT:
                    if(w.endPoint[2][0]==headx&&w.endPoint[2][2]==LEFT){
                        reachable[2][4]=false;
                        break;
                    }
                case UP_LEFT:
                case DOWN_LEFT:
                    if(w.endPoint[2][0]==headx&&w.endPoint[2][2]==RIGHT){
                        reachable[2][4]=false;
                        break;
                    }
            } 
        }
        if(endPointPresent[1]){
            switch(dir){
                case UP_RIGHT:
                    if(w.dir==UP_LEFT)
                        reachable[1][4]=false;
                    break;
                 case UP_LEFT:
                    if(w.dir==UP_RIGHT)
                        reachable[1][4]=false;
                    break;
                case DOWN_RIGHT:
                    if(w.dir==DOWN_LEFT)
                        reachable[1][4]=false;
                    break;
                case DOWN_LEFT:
                    if(w.dir==DOWN_RIGHT)
                        reachable[1][4]=false;
                    break;
            }
        }
    }
    public boolean checkfull(){
        int x,y;
        for(int i=0;i<w.wall.size();i++){
            if(abscissawall(i)>=xl_head&&abscissawall(i)<=xh_head&&ordinatewall(i)>=yl_head&&ordinatewall(i)<=yh_head)
                return true;
        }
        return false;
    }
    
    public void intermediateNode(){
        if(reachable[3][4])
            node=-1;
        else{
            if(endPointPresent[1]&&reachable[1][4]&&reachable[3][1]){
                node=1;
            }
            else if(endPointPresent[0]&&reachable[0][4]&&reachable[3][0]){
                node=0;
            }
            else if(endPointPresent[2]&&reachable[2][4]&&reachable[3][2]){
                node=2;
            }
        }
    }
    public void pathlength(int path,int sourcex,int sourcey, int destinationx, int destinationy){
        if(sourcex<destinationx){
            hor[path]=destinationx-sourcex;
            if(sourcey>destinationy){
                ver[path]=sourcey-destinationy;
                dir=UP_RIGHT;
                source_dest_dir1[0]=0;
                source_dest_dir1[1]=-1;
                source_dest_dir2[0]=1;
                source_dest_dir2[1]=0;
                source_destMove=new short[path][hor[path]+ver[path]];
            }
            if(sourcey<destinationy){
                ver[path]=destinationy-sourcey;
                dir=DOWN_RIGHT;
                source_dest_dir1[0]=0;
                source_dest_dir1[1]=1;
                source_dest_dir2[0]=1;
                source_dest_dir2[1]=0;
                source_destMove=new short[path][hor[path]+ver[path]];
            }
        }
        if(sourcex>destinationx){
            hor[path]=sourcex-destinationx;
            if(sourcey>destinationy){
                dir=UP_LEFT;
                ver[path]=sourcey-destinationy;
                source_dest_dir1[0]=0;
                source_dest_dir1[1]=-1;
                source_dest_dir2[0]=-1;
                source_dest_dir2[1]=0;
                source_destMove=new short[path][hor[path]+ver[path]];
            }
            if(sourcey<destinationy){
                dir=DOWN_LEFT;
                ver[path]=destinationy-sourcey;
                source_dest_dir1[0]=0;
                source_dest_dir1[1]=1;
                source_dest_dir2[0]=-1;
                source_dest_dir2[1]=0;
                source_destMove=new short[path][hor[path]+ver[path]];
            }
        }
    }
    public void storePath(int path){
        int pathlen=hor[path]+ver[path];
        RandomNumberGenerator choose=new RandomNumberGenerator(pathlen,0,2);
        int horstored=0,verstored=0;
        for(int storeCounter=0;storeCounter<pathlen;storeCounter++){
            if((choose.getRandomNumber()==0)||horstored==hor[path]){
                verstored++;
                finalPath.add(source_dest_dir1);
            }
            if((choose.getRandomNumber()==1)||verstored==ver[path]){
                horstored++;
                finalPath.add(source_dest_dir2);
            }
        }
    }
    public Short[] getdxdy(){
        if(this.isAlive() && finalPath.size()==0){
            temp[0]=0;
            temp[0]=0;
        }
        else{
            temp=((Short[]) finalPath.firstElement());
            finalPath.remove(0);
        }
        System.out.println("                                                ISNAKE MOVEMENT: ("+temp[0]+", "+temp[1]+")");
        return temp;
    }
    public int abscissawall(int index){
        return (((GameAreaCoordinate)(w.wall.elementAt(index))).getX());
    }
    public int ordinatewall(int index){
        return (((GameAreaCoordinate)(w.wall.elementAt(index))).getY());
    }
}
